基于注解的配置
XML 设置的替代方法是基于注释的配置,它依赖于字节码元数据来连接组件而不是角括号声明。开发人员通过使用相关类,方法或字段声明上的注释来将配置移动到组件类本身中,而不是使用 XML 来描述 bean 布线。例如,Spring2.0 引入了使用 @Required 注释实现 required 属性的可能性。Spring2.5 添加了对 JSR-250 注释的支持,例如 @PostConstruct 和 @PreDestroy。Spring3.0 增加了对 javax.inject 包中包含的 JSR-330(Java的依赖注入)注释的支持,例如 @Inject 和 @Named。
@required
@Required 注释适用于 bean 属性的 setter 方法,此注释表示被标注的 bean 属性必须在配置时通过 bean 定义中的显式属性值或通过自动装配被填充,如果被标注的 bean 属性未被填充,容器将抛出异常。如下例子所示:
@Autowired
Spring 通过 @Autowired 注解实现 Bean 的依赖注入,可以运用在多种自动注入场景。
应用于构造函数
Spring 框架4.3,如果目标 bean 只定义了一个构造函数,则可以不需要 @Autowired。如果有多个构造函数,则至少必须为其中一个声明注解,告知容器哪一个是必须被使用的。
应用于 setter 方法
|
|
应用于拥有参数的某个方法
|
|
应用于字段或与构造函数混合使用
|
|
应用于数组或集合
|
|
应用于泛型
原始类:
泛型类:
required 属性
如果容器中没有一个和标注变量类型匹配的 Bean,Spring 容器启动时会抛出异常,默认情况下,required 属性值为 true,即要求一定要找到匹配的 Bean。
@Primary
因为按类型自动装配可能导致多个候选项,所以通常需要对选择过程有更多的控制。@Primary 表示当多个 bean 自动装配到单值依赖关系的候选项时,应该优先选择 @Primary 指定的 bean。如果候选项中只有一个 primary bean,那么它将作为自动装配的值。
如下定义 firstMovieCatalog 作为 primary MovieCatalog:
@Qualifier
@Qualifier 可以将限定符值与特定参数相关联,缩小类型匹配集,以便为每个参数选择特定的 bean。如果容器中有一个以上匹配的 Bean 时,则可以通过 @Qualifier 注解限定 Bean 的名称。
@Qualifier 也可以用于独立的构造函数参数或方法参数:
@Resource
@Resource 要求提供一个 Bean 名称的属性,如果没有明确指定名称,则默认名称派生自字段名称或 setter 方法。在字段的情况下,它采用字段名称; 在 setter 方法的情况下,它接受 bean 属性名称。
以下示例使用名称为 movieFinder
的 bean 注入到其 setter 方法中:
@Autowired 默认按类型匹配注入 Bean,@Resource 则按名称匹配注入 Bean,@Inject 和 @Autowired 一样按类型匹配注入 Bean,只不过它没有 required 属性。
@PostConstruct 和 @PreDestroy
使用 <bean>
进行配置时,可以通过 init-method 和 destory-method 属性指定 Bean 的初始化及容器销毁前执行的方法。Spring 从 2.5 开始支持 JSR-250 中定义的 @PostConstruct 和 @PreDestroy 注解,在 Spring 中相当于 init-method 和 destory-method 属性的功能,不过使用注解时,可以在一个 Bean 中定义多个 @PostConstruct 和 @PreDestroy 方法。
基于 Java 类的配置
@Bean 注解用于表示方法实例化,配置和初始化一个由 Spring IoC 容器管理的新对象。@Bean 注释与 <bean/>
元素具有相同的作用。@Configuration 注解表示被标注的 POJO 类可以为 Spring 容器提供 Bean 定义的信息。
简单的实例如下:
与 AppConfig 类等同的 XML 配置:
@Bean
@Bean 是一个方法级别的注解和 XML <bean/>
元素的替代,它支持 init-method, destroy-method, autowiring 和 name 等 <bean/>
提供的属性。
@Scope
用于指定 Bean 的作用域。
自定义 Bean 的名称,别名和描述
Bean 可以通过 name 属性自定义名称,当有多个名称时,其它的为别名;还可以使用 @Description 定义 Bean 的描述信息。
@Configuration
@Configuration 是一个类级别的注解,表示该类是为 Spring 容器提供 bean 定义信息的类。
@Import
等同于 XML 配置中的 <import/>
元素,@Import 注解允许从另一个 Configuration 类中加载 @Bean 定义。
如上所述,ConfigB 中导入了 ConfigA,所以在实例化上下文的时候,只需要提供 ConfigB。
@ImportResource
用于加载资源文件路径的注解。
properties-config.xml
123<beans><context:property-placeholder location="classpath:/com/acme/jdbc.properties"/></beans>jdbc.properties
123jdbc.url=jdbc:hsqldb:hsql://localhost/xdbjdbc.username=sajdbc.password=bean 类
1234567891011121314"classpath:/com/acme/properties-config.xml")(public class AppConfig {"${jdbc.url}")(private String url;"${jdbc.username}")(private String username;"${jdbc.password}")(private String password;public DataSource dataSource() {return new DriverManagerDataSource(url, username, password);}}main 类
12345public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);TransferService transferService = ctx.getBean(TransferService.class);// ...}
不同配置方式的比较
描述 | 基于 XML 配置 | 基于注解配置 | 基于 Java 类配置 |
---|---|---|---|
Bean 定义 | 在 XML 文件中通过 <bean> 元素定义 Bean。如:<bean class="com.lake.UserDao"/> |
在 Bean 实现类出通过标注 @Component 或衍型类(@Repository、@Service 及 @Controller)定义 Bean | 在标注了 @Configuration 的 Java 类中,通过在类方法上标注 @Bean 定义一个 Bean,方法必须提供 Bean 的实例化逻辑 |
Bean 名称 | 通过 <bean> 的 id 或 name 属性定义 Bean。如:<bean id="userDao" class="com.lake.UserDao"/> ,默认名称为:com.lake.UserDao#0 |
通过注解的 value 属性定义,如 @Component(“userDao”),默认名称为小写字母开头的类名(不带包名):userDao | 通过 @Bean 的 name 属性定义,如 @Bean(“userDao”),默认名称为方法名 |
Bean 注入 | 通过 <property> 子元素或通过 p 命名空间的动态属性,如 p:userDao-ref=”userDao” 进行注入 |
通过在成员变更或方法入参处标注 @Autowired,按类型匹配自动注入,还可以配合使用 @Qualifier 按名称匹配方式注入 | 比较灵活,可以通过在方法处通过 @Autowired 使方法入参绑定 Bean,然后在方法中通过代码进行注入,还可通过调用配置类的 @Bean 方法进行注入 |
Bean 作用域 | 通过 <bean> 的 scpoe 属性指定,如:<bean class="com.lake.UserDao" scope="prototype"/> |
通过在类定义处标注 @Scope 指定,如:@Scope(“prototype”) | 通过在 Bean 方法定义处标注 @Scope 指定 |
Bean 生命周期方法 | 通过 <bean> 的 init-method 和 destroy-method 属性指定 Bean 实现类的方法名,最多只能指定一个初始化方法和销毁方法 |
通过在目标方法上标注 @PostConstruct 和 @PreDestory 注解指定初始化或销毁方法,可以定义任意多个 | 通过 @Bean 的 initMethod 或 destoryMethod 指定一个初始化或销毁方法。对于初始化方法来说,可以直接在方法内部通过代码的方式灵活定义初始化逻辑 |
Bean 延迟初始化 | 通过 <bean> 的 lazy-init 属性指定,默认为 default,继承自 <beans> 的 default-lazy-init 设置,该值默认为 false |
通过在类定义出标注 @Lazy 指定,如:@Lazy(true) | 通过在 Bean 方法定义出标注 @Lazy 指定 |
适合场景 | Bean 实现类来源于第三方类库,如 DataSource、JdbcTemplate 等,因无法在类中标注注解,通过 XML 配置方式较好;命名空间的配置,如 aop、context 等,只能采用基于 XML 的配置 | Bean 的实现类时当前项目开发的,可以直接在 Java 类中使用基于注解的配置 | 优势在于可以通过代码的方式控制 Bean 初始化的整体逻辑,所以如果实例化 Bean 的逻辑比较复杂,则比较适合用基于 Java 类配置的方式 | |